home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 March / EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso / earcd / patches / dungeon.lha / Dungeon / Source.lha / amiga.c < prev    next >
C/C++ Source or Header  |  1995-10-15  |  14KB  |  589 lines

  1. /**********************************/
  2. /*                  */
  3. /* Amiga text adventure front-end */
  4. /* Copyright 1995 David Kinder      */
  5. /*                  */
  6. /**********************************/
  7.  
  8. #include <clib/asl_protos.h>
  9. #include <clib/exec_protos.h>
  10. #include <clib/intuition_protos.h>
  11. #include <clib/gadtools_protos.h>
  12. #include <clib/graphics_protos.h>
  13. #include <clib/macros.h>
  14. #include <exec/exec.h>
  15. #include <graphics/videocontrol.h>
  16. #include <ctype.h>
  17. #include <stdarg.h>
  18. #include <string.h>
  19. #include "amiga.h"
  20.  
  21. #define SHIFT (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)
  22. #define HISTORY_SIZE 10
  23. enum chars
  24.   { CHAR_LEFT = 0x100,
  25.     CHAR_SHIFTLEFT,
  26.     CHAR_RIGHT,
  27.     CHAR_SHIFTRIGHT,
  28.     CHAR_UP,
  29.     CHAR_DOWN };
  30.  
  31. extern struct Library *IntuitionBase, *GfxBase;
  32. extern struct Library *GadToolsBase, *AslBase;
  33.  
  34. struct Window *TextWindow;
  35. struct RastPort *TextRPort;
  36. struct Menu *Menus;
  37. struct FileRequester *FileReq;
  38. APTR Visual;
  39. UWORD MinWidth, MinHeight, TextLeft, TextRight, TextBorder, TextHeight;
  40. char TextBuffer[4096];
  41. char LineBuffer[512];
  42. UWORD LinePos, MoreCount;
  43. BOOL QuitExit = FALSE;
  44. char *History[HISTORY_SIZE];
  45.  
  46. struct NewMenu NewMenus[] =
  47.  {{ NM_TITLE,"Project",0,0,0,0 },
  48.   { NM_ITEM,"About...","?",0,0,0 },
  49.   { NM_ITEM,"Quit","Q",0,0,0 },
  50.   { NM_END,0,0,0,0 }};
  51.  
  52. void FlushText(void);
  53. int GetCharacter(char c,char *buffer);
  54. void CursorLeft(void);
  55. void CursorBottomLeft(void);
  56. void ScrollWindow(void);
  57. void DrawCursor(BOOL on, char c);
  58. void GetScreenSize(struct Screen *scr, ULONG *w, ULONG *h);
  59. void AddToHistory(char *buffer);
  60. int UseHistory(char *buffer, int hpos, int left);
  61. UWORD GetTextHeight(int sub);
  62.  
  63. wbmain()
  64. {
  65.   main();
  66. }
  67.  
  68. void AmigaSetup()
  69. {
  70. struct Screen *defscr;
  71. ULONG width,height;
  72.  
  73.   if (IntuitionBase->lib_Version < 37) AmigaExit(1);
  74.  
  75.   if ((defscr = LockPubScreen(NULL)) == NULL) AmigaExit(1);
  76.   GetScreenSize(defscr,&width,&height);
  77.   if ((TextWindow = OpenWindowTags(NULL,
  78.     WA_Left,0,
  79.     WA_Top,defscr->BarHeight+1,
  80.     WA_Width,width,
  81.     WA_Height,height - defscr->BarHeight - 1,
  82.     WA_Flags,
  83.       WFLG_ACTIVATE|WFLG_CLOSEGADGET|WFLG_SIZEGADGET|WFLG_SIZEBBOTTOM|
  84.       WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_SMART_REFRESH|WFLG_NEWLOOKMENUS,
  85.     WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_CHANGEWINDOW|IDCMP_VANILLAKEY|
  86.        IDCMP_RAWKEY|IDCMP_MENUPICK,
  87.     WA_Title,"Dungeon",
  88.     WA_ScreenTitle,"Dungeon",
  89.     WA_PubScreen,defscr,
  90.     WA_AutoAdjust,TRUE,TAG_DONE)) == NULL) AmigaExit(1);
  91.   ScreenToFront(defscr);
  92.   UnlockPubScreen(NULL,defscr);
  93.  
  94.   if ((Visual = GetVisualInfo(TextWindow->WScreen,TAG_DONE)) == NULL)
  95.     AmigaExit(1);
  96.   if ((Menus = CreateMenus(NewMenus,GTMN_NewLookMenus,TRUE,TAG_DONE))
  97.     == NULL) AmigaExit(1);
  98.   LayoutMenus(Menus,Visual,GTMN_NewLookMenus,TRUE,TAG_DONE);
  99.   SetMenuStrip(TextWindow,Menus);
  100.  
  101.   if ((FileReq = AllocAslRequestTags(ASL_FileRequest,
  102.     ASLFR_Window,TextWindow,
  103.     ASLFR_SleepWindow,TRUE,
  104.     ASLFR_RejectIcons,TRUE,
  105.     ASLFR_InitialFile,"Dungeon.Save",TAG_DONE)) == NULL) AmigaExit(1);
  106.  
  107.   TextRPort = TextWindow->RPort;
  108.   SetAPen(TextRPort,1);
  109.   SetBPen(TextRPort,0);
  110.   SetDrMd(TextRPort,JAM2);
  111.  
  112.   TextLeft = TextWindow->BorderLeft;
  113.   TextRight = TextWindow->BorderRight;
  114.   TextBorder = TextLeft+TextRight+2;
  115.   MinWidth = TextBorder+(20*TextRPort->TxWidth);
  116.   MinHeight = TextWindow->BorderTop+TextWindow->BorderBottom+
  117.     (5*TextRPort->TxHeight);
  118.   TextHeight = GetTextHeight(0)/TextRPort->TxHeight;
  119.  
  120.   CursorBottomLeft();
  121. }
  122.  
  123. void AmigaExit(int code)
  124. {
  125. int i;
  126.  
  127.   if ((TextWindow) && (QuitExit == FALSE))
  128.   {
  129.     AmigaPrintF("\n[Press any key.]");
  130.     FlushText();
  131.     GetCharacter(0,0);
  132.   }
  133.   for (i = 0; i < HISTORY_SIZE; i++)
  134.     if (History[i] != NULL) FreeVec(History[i]);
  135.   if (FileReq) FreeAslRequest(FileReq);
  136.   if (Menus) FreeMenus(Menus);
  137.   if (Visual) FreeVisualInfo(Visual);
  138.   if (TextWindow) CloseWindow(TextWindow);
  139.   exit(code);
  140. }
  141.  
  142. void AmigaPrintF(const char *format,...)
  143. {
  144. va_list va;
  145. char *current = TextBuffer;
  146. BOOL ret = FALSE;
  147.  
  148.   va_start(va,format);
  149.   vsprintf(TextBuffer,format,va);
  150.   va_end(va);
  151. /*
  152.   while (*current != '\0') AmigaPutChar(*current++);*/
  153. int i;
  154.   for (i = 0; i< 100; i++)
  155.     if (*current != '\0') AmigaPutChar(*current++);
  156. }
  157.  
  158. void AmigaPutChar(char c)
  159. {
  160. int i;
  161.  
  162.   switch (c)
  163.   {
  164.     case '\t':
  165.       for (i = 0; i < 8; i++) AmigaPutChar(' ');
  166.       break;
  167.     case '\n':
  168.       FlushText();
  169.       if (TextRPort->cp_y < GetTextHeight(1)+TextWindow->BorderTop+
  170.     TextRPort->TxBaseline)
  171.       {
  172.     SetAPen(TextRPort,1);
  173.     Move(TextRPort,TextLeft+1,TextRPort->cp_y+TextRPort->TxHeight);
  174.       }
  175.       else ScrollWindow();
  176.  
  177.       MoreCount++;
  178.       if (MoreCount >= (GetTextHeight(0)/TextRPort->TxHeight)-1)
  179.       {
  180.     AmigaPrintF("[MORE]");
  181.     FlushText();
  182.         GetCharacter(0,0);
  183.     CursorLeft();
  184.     AmigaPrintF("      ");
  185.     FlushText();
  186.     CursorLeft();
  187.     MoreCount = 0;
  188.       }
  189.       break;
  190.     default:
  191.       if (isprint((unsigned char)c) != 0)
  192.       {
  193.     *(LineBuffer+LinePos) = c;
  194.     LinePos++;
  195.       }
  196.       break;
  197.   }
  198. }
  199.  
  200. void AmigaGetString(char *buffer, int len)
  201. {
  202. int c, end = 0, cursor = 0, hpos = -1;
  203. UWORD left;
  204.  
  205.   MoreCount = 0;
  206.   *buffer = '\0';
  207.   FlushText();
  208.   left = TextRPort->cp_x;
  209.   SetAPen(TextRPort,2);
  210.   for (;;)
  211.   {
  212.     c = GetCharacter(*(buffer+cursor),buffer);
  213.     switch (c)
  214.     {
  215.       case 0x0D:
  216.     *(buffer+end) = '\n';
  217.     *(buffer+end+1) = '\0';
  218.     AmigaPutChar('\n');
  219.     AddToHistory(buffer);
  220.     return;
  221.     break;
  222.       case 0x7F:
  223.     if ((end > 0) && (cursor < end))
  224.     {
  225.       memmove(buffer+cursor,buffer+cursor+1,end-cursor+1);
  226.       ClipBlit(TextRPort,
  227.         TextRPort->cp_x+TextRPort->TxWidth,
  228.         TextRPort->cp_y-TextRPort->TxBaseline,
  229.         TextRPort,
  230.         TextRPort->cp_x,
  231.         TextRPort->cp_y-TextRPort->TxBaseline,
  232.         TextWindow->Width-TextRight-TextRPort->cp_x-TextRPort->TxWidth,
  233.         TextRPort->TxHeight,0xC0);
  234.       end--;
  235.     }
  236.     break;
  237.       case 0x08:
  238.     if ((end > 0) && (cursor > 0))
  239.     {
  240.       memmove(buffer+cursor-1,buffer+cursor,end-cursor+1);
  241.       ClipBlit(TextRPort,
  242.         TextRPort->cp_x,
  243.         TextRPort->cp_y-TextRPort->TxBaseline,
  244.         TextRPort,
  245.         TextRPort->cp_x-TextRPort->TxWidth,
  246.         TextRPort->cp_y-TextRPort->TxBaseline,
  247.         TextWindow->Width-TextRight-TextRPort->cp_x-TextRPort->TxWidth,
  248.         TextRPort->TxHeight,0xC0);
  249.       Move(TextRPort,TextRPort->cp_x-TextRPort->TxWidth,
  250.         TextRPort->cp_y);
  251.       end--;
  252.       cursor--;
  253.     }
  254.     break;
  255.       case CHAR_LEFT:
  256.     if (cursor > 0)
  257.     {
  258.       cursor--;
  259.       Move(TextRPort,TextRPort->cp_x-TextRPort->TxWidth,
  260.         TextRPort->cp_y);
  261.     }
  262.     break;
  263.       case CHAR_SHIFTLEFT:
  264.     if (cursor > 0)
  265.     {
  266.       Move(TextRPort,left,TextRPort->cp_y);
  267.       cursor = 0;
  268.     }
  269.     break;
  270.       case CHAR_RIGHT:
  271.     if (cursor < end)
  272.     {
  273.       cursor++;
  274.       Move(TextRPort,TextRPort->cp_x+TextRPort->TxHeight,
  275.         TextRPort->cp_y);
  276.     }
  277.     break;
  278.       case CHAR_SHIFTRIGHT:
  279.     if (cursor < end)
  280.     {
  281.       Move(TextRPort,TextRPort->cp_x+(TextRPort->TxWidth*(end-cursor)),
  282.         TextRPort->cp_y);
  283.       cursor = end;
  284.     }
  285.     break;
  286.       case CHAR_UP:
  287.     if ((hpos < HISTORY_SIZE-1) && (History[hpos+1]))
  288.       cursor = end = UseHistory(buffer,++hpos,left);
  289.     break;
  290.       case CHAR_DOWN:
  291.     if ((hpos > 0) && (History[hpos-1]))
  292.       cursor = end = UseHistory(buffer,--hpos,left);
  293.     else
  294.       cursor = end = UseHistory(buffer,-1,left);
  295.     break;
  296.       default:
  297.     if ((end < len-2) && (isprint((unsigned char)c) != 0) &&
  298.       ( c < 128) && (TextRPort->cp_x+(TextRPort->TxWidth*2) <
  299.       TextWindow->Width-TextRight))
  300.     {
  301.       memmove(buffer+cursor+1,buffer+cursor,end-cursor+1);
  302.       *(buffer+cursor++) = c;
  303.       ClipBlit(TextRPort,
  304.         TextRPort->cp_x,
  305.         TextRPort->cp_y-TextRPort->TxBaseline,
  306.         TextRPort,
  307.         TextRPort->cp_x+TextRPort->TxWidth,
  308.         TextRPort->cp_y-TextRPort->TxBaseline,
  309.         TextWindow->Width-TextRight-TextRPort->cp_x-TextRPort->TxWidth,
  310.         TextRPort->TxHeight,0xC0);
  311.       end++;
  312.       AmigaPutChar(c);
  313.       FlushText();
  314.     }
  315.     break;
  316.     }
  317.   }
  318. }
  319.  
  320. int AmigaSave(char *buffer)
  321. {
  322.   if (AslRequestTags(FileReq,
  323.     ASLFR_TitleText,"Save Game",
  324.     ASLFR_DoSaveMode,TRUE,TAG_DONE))
  325.   {
  326.     strcpy(buffer,FileReq->fr_Drawer);
  327.     AddPart(buffer,FileReq->fr_File);
  328.     return TRUE;
  329.   }
  330.   return FALSE;
  331. }
  332.  
  333. int AmigaLoad(char *buffer)
  334. {
  335.   if (AslRequestTags(FileReq,
  336.     ASLFR_TitleText,"Load Game",
  337.     ASLFR_DoSaveMode,FALSE,TAG_DONE))
  338.   {
  339.     strcpy(buffer,FileReq->fr_Drawer);
  340.     AddPart(buffer,FileReq->fr_File);
  341.     return TRUE;
  342.   }
  343.   return FALSE;
  344. }
  345.  
  346. void FlushText()
  347. {
  348. char *ptr;
  349. int line;
  350.  
  351.   if (LinePos > 0)
  352.   {
  353.     ptr = LineBuffer;
  354.     line = (TextWindow->Width-TextBorder)/TextRPort->TxWidth;
  355.     if (LinePos > line)
  356.     {
  357.       while (LinePos > line)
  358.       {
  359.     Text(TextRPort,ptr,line);
  360.     ptr += line;
  361.     LinePos -= line;
  362.     line = (TextWindow->Width-TextBorder)/TextRPort->TxWidth;
  363.     ScrollWindow();
  364.       }
  365.     }
  366.     if (LinePos > 0) Text(TextRPort,ptr,LinePos);
  367.     LinePos = 0;
  368.   }
  369. }
  370.  
  371. int GetCharacter(char c,char *buffer)
  372. {
  373. struct IntuiMessage *imsg;
  374. ULONG class;
  375. UWORD code, qualifier, xpos;
  376.  
  377. static struct EasyStruct req =
  378.   { sizeof(struct EasyStruct),0,"Dungeon",
  379.     "Dungeon 2.7A\n\n"
  380.     "Dungeon was originally written by the founders of\n"
  381.     "Infocom, Inc. when they were at MIT in the late\n"
  382.     "seventies. This version has been ported to the\n"
  383.     "Amiga by David Kinder.","Continue" };
  384.  
  385.   DrawCursor(TRUE,c);
  386.   for (;;)
  387.   {
  388.     while (imsg = (struct IntuiMessage *)GetMsg(TextWindow->UserPort))
  389.     {
  390.       class = imsg->Class;
  391.       code = imsg->Code;
  392.       qualifier = imsg->Qualifier;
  393.       ReplyMsg((struct Message *)imsg);
  394.       switch (class)
  395.       {
  396.     case IDCMP_VANILLAKEY:
  397.       DrawCursor(FALSE,c);
  398.       return code;
  399.       break;
  400.     case IDCMP_RAWKEY:
  401.       switch (code)
  402.       {
  403.         case 0x4C:
  404.           DrawCursor(FALSE,c);
  405.           return CHAR_UP;
  406.           break;
  407.         case 0x4D:
  408.           DrawCursor(FALSE,c);
  409.           return CHAR_DOWN;
  410.           break;
  411.         case 0x4E:
  412.           DrawCursor(FALSE,c);
  413.           return (qualifier & SHIFT) ? CHAR_SHIFTRIGHT : CHAR_RIGHT;
  414.           break;
  415.         case 0x4F:
  416.           DrawCursor(FALSE,c);
  417.           return (qualifier & SHIFT) ? CHAR_SHIFTLEFT : CHAR_LEFT;
  418.           break;
  419.       }
  420.       break;
  421.     case IDCMP_CLOSEWINDOW:
  422.       QuitExit = TRUE;
  423.       SetAPen(TextRPort,0);
  424.       fini_();
  425.       break;
  426.     case IDCMP_MENUPICK:
  427.       if (MENUNUM(code) == 0)
  428.       {
  429.         switch (ITEMNUM(code))
  430.          {
  431.           case 0:
  432.         EasyRequest(TextWindow,&req,NULL);
  433.         break;
  434.           case 1:
  435.         QuitExit = TRUE;
  436.         SetAPen(TextRPort,0);
  437.             fini_();
  438.         break;
  439.         }
  440.       }
  441.       break;
  442.     case IDCMP_CHANGEWINDOW:
  443.       if ((GetTextHeight(0)/TextRPort->TxHeight) < TextHeight)
  444.       {
  445.         if (GetTextHeight(1)+TextWindow->BorderTop+TextRPort->TxBaseline
  446.           < TextRPort->cp_y)
  447.         {
  448.           xpos = TextRPort->cp_x;
  449.           SetAPen(TextRPort,0);
  450.           RectFill(TextRPort,
  451.         TextLeft,
  452.         TextWindow->BorderTop+GetTextHeight(1),
  453.         TextWindow->Width-TextRight-1,
  454.         TextWindow->Height-TextWindow->BorderBottom-1);
  455.           CursorBottomLeft();
  456.           if (buffer)
  457.           {
  458.         SetAPen(TextRPort,1);
  459.         AmigaPutChar('>');
  460.         FlushText();
  461.         SetAPen(TextRPort,2);
  462.         AmigaPrintF("%s",buffer);
  463.         FlushText();
  464.           }
  465.           SetAPen(TextRPort,2);
  466.           Move(TextRPort,xpos,TextRPort->cp_y);
  467.           DrawCursor(TRUE,c);
  468.         }
  469.       }
  470.       TextHeight = GetTextHeight(0)/TextRPort->TxHeight;
  471.       break;
  472.       }
  473.     }
  474.     WaitPort(TextWindow->UserPort);
  475.   }
  476. }
  477.  
  478. void CursorLeft()
  479. {
  480.   Move(TextRPort,TextLeft+1,TextRPort->cp_y);
  481. }
  482.  
  483. void CursorBottomLeft()
  484. {
  485.   Move(TextRPort,
  486.        TextLeft+1,
  487.        GetTextHeight(1)+TextWindow->BorderTop+TextRPort->TxBaseline);
  488. }
  489.  
  490. void ScrollWindow()
  491. {
  492.   WaitTOF();
  493.   ClipBlit(TextRPort,
  494.        TextLeft,
  495.        TextWindow->BorderTop+TextRPort->TxHeight,
  496.        TextRPort,
  497.        TextLeft,
  498.        TextWindow->BorderTop,
  499.        TextWindow->Width-TextLeft-TextRight,
  500.        GetTextHeight(1),
  501.        0xC0);
  502.   SetAPen(TextRPort,0);
  503.   RectFill(TextRPort,
  504.        TextLeft,
  505.        TextWindow->BorderTop+GetTextHeight(1),
  506.        TextWindow->Width-TextRight-1,
  507.        TextWindow->BorderTop+GetTextHeight(0)-1);
  508.   SetAPen(TextRPort,1);
  509.   CursorBottomLeft();
  510. }
  511.  
  512. void DrawCursor(BOOL on, char c)
  513. {
  514. WORD xpos;
  515. BYTE fgpen;
  516.  
  517.   if (c == 0) c = ' ';
  518.   xpos = TextRPort->cp_x;
  519.   fgpen = TextRPort->FgPen;
  520.   SetAPen(TextRPort,on ? 1 : 2);
  521.   SetBPen(TextRPort,on ? 3 : 0);
  522.   Text(TextRPort,&c,1);
  523.   SetAPen(TextRPort,fgpen);
  524.   SetBPen(TextRPort,0);
  525.   Move(TextRPort,xpos,TextRPort->cp_y);
  526.  
  527.   if (on)
  528.     WindowLimits(TextWindow,
  529.       MAX(xpos+TextRPort->TxWidth+TextRight+1,MinWidth),MinHeight,-1,-1);
  530.   else
  531.     WindowLimits(TextWindow,TextWindow->Width,TextWindow->Height,
  532.       TextWindow->Width,TextWindow->Height);
  533. }
  534.  
  535. void GetScreenSize(struct Screen *scr, ULONG *w, ULONG *h)
  536. {
  537. struct TagItem vti[] =
  538.   { VTAG_VIEWPORTEXTRA_GET,NULL,
  539.     VTAG_END_CM,NULL };
  540. struct ViewPortExtra *vpe;
  541.  
  542.   *w = scr->Width;
  543.   *h = scr->Height;
  544.   if (scr->ViewPort.ColorMap)
  545.   {
  546.     if (VideoControl(scr->ViewPort.ColorMap,vti) == 0)
  547.     {
  548.       vpe = (struct ViewPortExtra *)vti[0].ti_Data;
  549.       *w = vpe->DisplayClip.MaxX - vpe->DisplayClip.MinX + 1;
  550.       *h = vpe->DisplayClip.MaxY - vpe->DisplayClip.MinY + 1;
  551.     }
  552.   }
  553. }
  554.  
  555. void AddToHistory(char *buffer)
  556. {
  557. char *hist;
  558. int i;
  559.  
  560.   if (strcmp(buffer,"\n") == 0) return;
  561.   if ((hist = AllocVec(strlen(buffer),MEMF_CLEAR)) == NULL) return;
  562.   strncpy(hist,buffer,strlen(buffer)-1);
  563.   if (History[HISTORY_SIZE-1] != NULL) FreeVec(History[HISTORY_SIZE-1]);
  564.   for (i = HISTORY_SIZE-1; i > 0; i--) History[i] = History[i-1];
  565.   History[0] = hist;
  566. }
  567.  
  568. int UseHistory(char *buffer, int hpos, int left)
  569. {
  570.   strcpy(buffer,(hpos > -1) ? History[hpos] : "");
  571.   SetAPen(TextRPort,0);
  572.   RectFill(TextRPort,
  573.     left,
  574.     TextRPort->cp_y-TextRPort->TxBaseline,
  575.     TextWindow->Width-TextRight-1,
  576.     TextRPort->cp_y-TextRPort->TxBaseline+TextRPort->TxHeight-1);
  577.   SetAPen(TextRPort,2);
  578.   Move(TextRPort,left,TextRPort->cp_y);
  579.   Text(TextRPort,buffer,strlen(buffer));
  580.   return strlen(buffer);
  581. }
  582.  
  583. UWORD GetTextHeight(int sub)
  584. {
  585.   return
  586.     (((TextWindow->Height-TextWindow->BorderTop-TextWindow->BorderBottom)
  587.     /TextRPort->TxHeight)-sub)*TextRPort->TxHeight;
  588. }
  589.